package springbatch;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/*
 * 说明:使用此方法必须把xml文件子节点到到根节点所有的path，作为一个字符串数组，传入方法。
 * 例如：取得节点testKey42的值，参数为：new String[] { "testKey42", "testKey2", "testKey1", "searchLabel", "screen" }
	<?xml version="1.0" encoding="UTF-8"?>
	<screen>
		<searchLabel>
			<testKey1>
				<testKey2>
					<testKey41>testValue41</testKey41>
					<testKey42>testValue42</testKey42>
				</testKey2>
			</testKey1>
		</searchLabel>
	</screen>
 */
public class XMLUtils {
	
	public static String xml = "";

	private static DocumentBuilderFactory builderFactory = DocumentBuilderFactory
			.newInstance();

	private static DocumentBuilder builder;

	private static Map<String, String> xmlMap = new HashMap<String, String>();

	public static final String XML_NODE_NAME_SCREEN = "screen";
	public static final String XML_NODE_NAME_TESTKEY42 = "testKey42";
	public static final String XML_NODE_NAME_TESTKEY2 = "testKey2";
	public static final String XML_NODE_NAME_TESTKEY1 = "testKey1";
	public static final String XML_NODE_NAME_SEARCHLABEL = "searchLabel";

	
	/**
	 * 
	 */
	public static void init() {
		Document document = parse("src/springbatch/screen.xml");
		Element root = document.getDocumentElement(); // 取得根节点
		foreachXmlToMap(root, root);
	}
	
	/**
	 * get value from XML
	 * 
	 * @param xmlNodeNames 全路径节点名
	 * @return
	 */
	public static String getValueFromXml(String[] xmlNodeNames) {
		
		if (xmlMap.size() == 0) {
			init();
		}
		////test
		init();
		//;
		return xmlMap.get(buildXmlkey(xmlNodeNames));
	}
	
	/**
	 * get value from XML
	 * 
	 * @param xmlNodeNames 全路径节点名
	 * @return
	 */
	private static String buildXmlkey(String[] xmlNodeNames) {
		if (xmlNodeNames == null) {
			return null;
		}

		String xmlKeys = "|";
		for (String str : xmlNodeNames) {
			xmlKeys += str + "|";
		}

		return xmlKeys;
	}
	
	/**
	 * Load and parse XML file into DOM
	 * 
	 * @param filePath xml文件路径
	 * @return
	 */
	private static Document parse(String filePath) {
		Document document = null;
		try {
			// DOM parser instance
			builder = builderFactory.newDocumentBuilder();
			// parse an XML file into a DOM tree
			document = builder.parse(new File(filePath));
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return document;
	}
	
	/***************************************************************************
	 * 得到指定节点下的所有文本内容,包括节点(逆归)
	 * 
	 * @param rootNode xml根节点
	 * @param e 要获取的节点对象
	 * @return
	 */
	private static String foreachXmlToMap(Node rootNode, Element e) {
		if (e != null) {

			if (e.getChildNodes() != null) {
				NodeList nodeList = e.getChildNodes();
				xml += "<" + e.getNodeName() + ">";

				for (int i = 0; i < nodeList.getLength(); i++) {

					Node node = nodeList.item(i);
					if (node.getChildNodes().getLength() > 0) {
						foreachXmlToMap(rootNode, (Element) node);
					} else {
						xml += node.getNodeValue() + "";

						if (node.getNodeType() == Node.TEXT_NODE) {
							// put xml key|key|... into map
							xmlMap.put(
									getParentElements(rootNode, node, null),
									node.getNodeValue());
						}
					}
				}
				xml += "</" + e.getNodeName() + ">";
			} else {
				xml += "<" + e.getNodeName() + ">" + e.getNodeValue() + "</"
						+ e.getNodeName() + ">";
			}
		}
		return xml;
	}

	private static String getParentElements(Node rootNode, Node node,
			StringBuilder parentElements) {

		if (parentElements == null) {
			parentElements = new StringBuilder();
		}

		if (node.getParentNode() == null) {
			// 如果是DOCUMENT类型，则不添加节点名
			if (node.getNodeType() != Node.DOCUMENT_NODE) {
				// parentElements.append(node.getNodeName());
			}

		} else if (node.getParentNode().isEqualNode(rootNode)) {
			parentElements.append(node.getNodeName() + "|");
			getParentElements(rootNode, node.getParentNode(), parentElements);
		} else {
			// 如果是TEXT类型，则不添加节点名
			if (node.getNodeType() == Node.TEXT_NODE) {
				parentElements.append("|");
			} else {
				parentElements.append(node.getNodeName() + "|");
			}
			getParentElements(rootNode, node.getParentNode(), parentElements);
		}
		return parentElements.toString();
	}

	/**
	 * 通过父节点对象和子节点名称取得子节点
	 * 
	 * @param fatherNode 父节点对象
	 * @param childNodeName 子节点名称
	 * @return
	 */
	private static Element getChildNode(Element fatherNode, String childNodeName) {
		if (childNodeName == null) {
			return null;
		}

		NodeList childNodes = fatherNode.getChildNodes();
		for (int j = 0; j < childNodes.getLength(); j++) {
			Node childNode = childNodes.item(j);
			// 如果这个节点属于Element ,再进行取值
			if (childNode instanceof Element) {
				if (childNode.getNodeName().equals(childNodeName)) {
					return (Element) childNode;
				}

			}

		}
		return null;
	}
		
	/***************************************************************************
	 * 取得指定节点名称的节点值
	 * 
	 * @param document xml文档对象
	 * @param nodeNames 节点名
	 * @return
	 */
	public static String getNodeValue(Document document, String[] nodeNames) {
		String nodeName = null;
		if (nodeNames == null || nodeNames.length < 1) {
			return null;
		}

		NodeList nodeList = document.getElementsByTagName(nodeNames[0]);
		Node fatherNode = nodeList.item(0);

		if (nodeNames.length == 1) {
			nodeName = fatherNode.getFirstChild().getNodeValue();
			return nodeName;
		}

		for (int i = 1; i < nodeNames.length; i++) {

			Node childNode = getChildNode((Element) fatherNode, nodeNames[i]);
			fatherNode = childNode;

			if (fatherNode instanceof Element) {
				if (fatherNode.getNodeType() == Node.ELEMENT_NODE) {
					if (i == nodeNames.length - 1) {
						nodeName = ((Element) fatherNode).getFirstChild()
								.getNodeValue();
						return nodeName;
					} else {
						continue;
					}

				} else if (fatherNode.getNodeType() == Node.TEXT_NODE) {
					// 如果是文本类型，则输出节点值，及文本内容
					if (i == nodeNames.length - 1) {
						nodeName = fatherNode.getNodeValue();
						;
						return nodeName;
					}
				}

			}

		}
		return nodeName;
	}

	
	public static void main(String[] args) throws FileNotFoundException,
			IOException {
		
		Document document = parse("E:/d20131014-wjq-swing-project/20131016_現地の業務処理パラメータ（ジャーナル照会関連）/conf/JNLAuthorityCheck.xml");
		Element root = document.getDocumentElement(); // 取得根节点
		
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■>>
		//遍历xml输出至控制台
		System.out.println(foreachXmlToMap(root, root));
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■<<
		
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■>>
		//取得指定节点名称的节点值
		System.out.println(getNodeValue(document,
				new String[] { "journal_authority_check1", "valid_condition2",
						"store", "min" }));
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■<<
		
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■>>
		document = parse("src/springbatch/screen.xml");
		System.out.println(getNodeValue(document,
				new String[] { "searchLabel","txtUserIDKey" }));		
		
		document = parse("src/springbatch/screen.xml");
		System.out.println(getNodeValue(document,
				new String[] { "testKey41" }));
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■<<
		
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■>>
		//这样取不到值,应该值得全部节点路径
		document = parse("src/springbatch/screen.xml");
		System.out.println(getNodeValue(document,
				new String[] { "searchLabel","testKey41" }));
		
		document = parse("E:/20131014-wjq-swing-project/20131016_現地の業務処理パラメータ（ジャーナル照会関連）/conf/JNLAuthorityCheck.xml");
		System.out.println(getNodeValue(document,
				new String[] {"journal_authority_check3", "valid_condition1","grade","max" }));
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■<<
		
		//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■>>
		System.out.println("--------------------");
		
		//遍历Map中保存的节点值和节点全路径
		for (String str : xmlMap.keySet()) {  
		      System.out.println(str+":::"+xmlMap.get(str));  
		}

		String[] strArgs = new String[] { XML_NODE_NAME_TESTKEY42,
				XML_NODE_NAME_TESTKEY2, XML_NODE_NAME_TESTKEY1,
				XML_NODE_NAME_SEARCHLABEL, XML_NODE_NAME_SCREEN };
		System.out.println(strArgs + ":::" + getValueFromXml(strArgs));
		System.out.println("--------------------");
		// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■<<
	}

}